/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.vce.election.web;

import com.vce.Audit;
import com.vce.BusinessException;
import com.vce.election.domain.*;
import com.vce.web.ManagedBean;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.vce.web.jsf.ObjectConverter;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ValueChangeEvent;
import org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException;

/**
 *
 * @author Ggutierrez
 */
public class TownDocumentBean extends ManagedBean {

    private ElectionType electionType;
    private Counting counting;  // Rapido, paralelo, oficial
    private Round round; // Primera, Segunda
    private Document document;
    private Town town;
    private BallotCentre ballotCentre;
    private Jrv jrv;
    private Set<Vote> votes;
    private List<Town> towns;
    private List<BallotCentre> ballots;
    private List<Jrv> jrvs;
    private Long voteFsln;
    private Long votePlc;
    private Long voteAln;
    private Long voteMrs;
    private Long votePrn;
    private Long voteAc;

    public TownDocumentBean() {
    }

    @Override
    public String startup() {
        String election = getParameterMap().get("election");
        if (election.equals("ALCALDE")){
            electionType = getElection().getCurrentElectionType(true);
        }else{
            electionType = getElection().getElectionType(4L);
        }
        
        counting = Counting.valueOf(getParameterMap().get("counting"));
        round = Round.valueOf(getParameterMap().get("round"));
        reset();
        return "success";
    }

    public String init() {
        electionType = getElection().getCurrentElectionType(true);
        counting = Counting.valueOf(getParameterMap().get("counting"));
        round = Round.valueOf(getParameterMap().get("round"));
        reset();
        return "success";
    }

    public String create() {
        reset();

        return "success";
    }

    public String save() {
        System.out.println("This is the save procedure");
        if (validations().equals("fail")) {
            return "fail";
        }

        if (jrv == null) {
            addErrorMessage("Debe informar la JRV");
            return "fail";
        }
        if (jrv != null && jrv.getCode() == null) {
            addErrorMessage("Debe informar codigo de la JRV");
            return "fail";
        }

        // Add votes for every Party
        // Plc
        Vote vPlc = new Vote();
        vPlc.setDocument(document);
        vPlc.setParty(getElection().getParty(9L));
        vPlc.setAmount(votePlc);
        votes.add(vPlc);

        // Fsln
        Vote vFsln = new Vote();
        vFsln.setDocument(document);
        vFsln.setParty(getElection().getParty(10L));
        vFsln.setAmount(voteFsln);
        votes.add(vFsln);

        // Aln
        Vote vAln = new Vote();
        vAln.setDocument(document);
        vAln.setParty(getElection().getParty(11L));
        vAln.setAmount(voteAln);
        votes.add(vAln);

        // Prn
        Vote vPrn = new Vote();
        vPrn.setDocument(document);
        vPrn.setParty(getElection().getParty(12L));
        vPrn.setAmount(votePrn);
        votes.add(vPrn);

        // Ac
        Vote vAc = new Vote();
        vAc.setDocument(document);
        vAc.setParty(getElection().getParty(13L));
        vAc.setAmount(voteAc);
        votes.add(vAc);

        document.setElectionType(electionType);
        document.setCounting(getCounting());
        document.setRound(getRound());
        document.setJrv(jrv);
        document.setVotes(votes);

        // Audit
        Audit audit = new Audit();
        audit.setCreatedBy(getElection().getCurrentUser());
        audit.setCreatedDate(new Date());
        audit.setModifiedBy(getElection().getCurrentUser());
        audit.setModifiedDate(new Date());

        document.setAudit(audit);
        calculations();

        try {
            getElection().storeDocument(document);
        } catch (HibernateOptimisticLockingFailureException e) {
            clear(document);
            return "fail";
        } catch (BusinessException e) {
            clear(document);
            addErrorMessage("Request was rejected, " + e.getMessage());
            return "fail";
        }

        addErrorMessage("Exito");
        System.out.println("Finished save process");
        reset();
        return "success";
    }

    public void clear(Document document) {
        document.getVotes().clear();
        document.setId(null);
    }

    @Override
    public void reset() {
        document = new Document();
        votes = new HashSet<Vote>();
        jrv = null;
        towns = null;
        ballots = null;
        town = null;
        ballotCentre = null;

        document.setDepositedVotes(0L);
        document.setValidVotes(0L);
        document.setNullVotes(0L);
        document.setCalcDepositedVotes(0L);
        document.setCalcValidVotes(0L);
    }

    public ElectionType getElectionType() {
        return electionType;
    }

    public void setElectionType(ElectionType electionType) {
        this.electionType = electionType;
    }

    public Document getDocument() {
        return document;
    }

    public void setDocument(Document document) {
        this.document = document;
    }

    public Counting getCounting() {
        return counting;
    }

    public void setCounting(Counting counting) {
        this.counting = counting;
    }

    public Round getRound() {
        return round;
    }

    public void setRound(Round round) {
        this.round = round;
    }

    public Town getTown() {
        return town;
    }

    public void setTown(Town town) {
        this.town = town;
    }

    public BallotCentre getBallotCentre() {
        return ballotCentre;
    }

    public void setBallotCentre(BallotCentre ballotCentre) {
        this.ballotCentre = ballotCentre;
    }

    public Jrv getJrv() {
        return jrv;
    }

    public void setJrv(Jrv jrv) {
        this.jrv = jrv;
    }

    public Set<Vote> getVotes() {
        return votes;
    }

    public void setVotes(Set<Vote> votes) {
        this.votes = votes;
    }

    public void setTowns(List<Town> towns) {
        this.towns = towns;
    }

    public List<Town> getTowns() {
        if (towns == null) {
            towns = getElection().findTowns();
            if (towns.size() > 0) {
                town = towns.get(0);
            } else {
                town = null;
            }
        }
        return towns;
    }

    public List<BallotCentre> getBallots() {
        if (ballots == null) {
            ballots = getElection().findBallotCentres(town);
            if (ballots.size() > 0) {
                ballotCentre = ballots.get(0);
            } else {
                ballotCentre = null;
            }
        }
        return ballots;
    }

    public void setBallots(List<BallotCentre> ballots) {
        this.ballots = ballots;
    }

    public List<Jrv> getJrvs() {
        return jrvs;
    }

    public void setJrvs(List<Jrv> jrvs) {
        this.jrvs = jrvs;
    }

    public void processTownChange(ValueChangeEvent event) throws AbortProcessingException {
        System.out.println("Town old value: " + ((Town) event.getOldValue()).getName());
        System.out.println("Town new value: " + ((Town) event.getNewValue()).getName());

        if (!((Town) event.getNewValue()).getId().equals(((Town) event.getOldValue()).getId())) {
            town = getElection().getTown(((Town) event.getNewValue()).getId());
            ballots = getElection().findBallotCentres(town);
            if (ballots.size() > 0) {
                ballotCentre = ballots.get(0);
            } else {
                ballotCentre = null;
            }
            FacesContext.getCurrentInstance().renderResponse();
        }
    }

    public void processBallotChange(ValueChangeEvent event) throws AbortProcessingException {
        System.out.println("Ballot old value: " + ((BallotCentre) event.getOldValue()).getDescription());
        System.out.println("Ballot new value: " + ((BallotCentre) event.getNewValue()).getDescription());

        if (!((BallotCentre) event.getNewValue()).getId().equals(((BallotCentre) event.getOldValue()).getId())) {
            ballotCentre = getElection().getBallotCentre(((BallotCentre) event.getNewValue()).getId());
            this.getJrvs();
            FacesContext.getCurrentInstance().renderResponse();
        }
    }

    public Long getVoteFsln() {
        return voteFsln;
    }

    public void setVoteFsln(Long vFsln) {
        this.voteFsln = vFsln;
    }

    public Long getVotePlc() {
        return votePlc;
    }

    public void setVotePlc(Long votePlc) {
        this.votePlc = votePlc;
    }

    public Long getVoteAln() {
        return voteAln;
    }

    public void setVoteAln(Long voteAln) {
        this.voteAln = voteAln;
    }

    public Long getVoteMrs() {
        return voteMrs;
    }

    public void setVoteMrs(Long voteMrs) {
        this.voteMrs = voteMrs;
    }

    public Long getVotePrn() {
        return votePrn;
    }

    public void setVotePrn(Long votePrn) {
        this.votePrn = votePrn;
    }

    public Long getVoteAc() {
        return voteAc;
    }

    public void setVoteAc(Long voteAc) {
        this.voteAc = voteAc;
    }

    public Integer getTotalInserted() {
        return (Integer) getElection().getTotalInsertedDocuments(getElection().getCurrentUser(), counting);
    }

    public Document getLastInsertedDocument() {
        return getElection().getlastInsertedDocument(getElection().getCurrentUser(), counting);
    }

    public void calculations() {
        Long nullVotes = document.getNullVotes();
        Long totalVotes = voteFsln + votePlc + voteAln + voteMrs + votePrn + voteAc;

        document.setCalcDepositedVotes(totalVotes + nullVotes);
        document.setCalcValidVotes(totalVotes);
    }

    public String validations() {
        Long limitVotes = 400L;
        Long nullVotes = document.getNullVotes();
        Long validVotes = document.getValidVotes();
        Long depositedvotes = document.getDepositedVotes();

        if (voteFsln == null) {
            voteFsln = 0L;
        }
        if (votePlc == null) {
            votePlc = 0L;
        }
        if (voteAln == null) {
            voteAln = 0L;
        }
        if (voteMrs == null) {
            voteMrs = 0L;
        }
        if (votePrn == null) {
            votePrn = 0L;
        }
        if (voteAc == null) {
            voteAc = 0L;
        }

        if (nullVotes == null) {
            nullVotes = 0L;
        }

        if (validVotes == null) {
            validVotes = 0L;
        }

        if (depositedvotes == null) {
            depositedvotes = 0L;
        }

        Long calcDepositedVotes = voteFsln + votePlc + voteAln + voteMrs + votePrn + voteAc + nullVotes;
        // Validar que no sea cero la suma
        if (calcDepositedVotes == 0L) {
            addErrorMessage("Suma de votos depositados igual a cero");
            return "fail";
        }

        if (depositedvotes == 0L) {
            addErrorMessage("Suma de votos depositados igual a cero");
            return "fail";
        }

        if (validVotes == 0L) {
            addErrorMessage("Suma de votos igual a cero");
            return "fail";
        }

        if (validVotes + nullVotes != depositedvotes) {
            addErrorMessage("Suma de votos invalida: Votos nulos + Votos Validos = Votos Depositados");
            return "fail";
        }

        // Validar que suma no sea mayor al rango de votos por JRV
        if (calcDepositedVotes > limitVotes) {
            addErrorMessage("Suma de votos mayor a la cantidad de votos por JRV");
            return "fail";
        }

        // Validar que las cantidades no sean menor que cero
        if (depositedvotes < 0L) {
            addErrorMessage("Suma de votos depositados no puede ser menor que cero");
            return "fail";
        }

        if (validVotes < 0L) {
            addErrorMessage("Suma de votos validos no puede ser menor que cero");
            return "fail";
        }

        if (nullVotes < 0L) {
            addErrorMessage("Votos nulos no puede ser menor que cero");
            return "fail";
        }

        if (calcDepositedVotes < 0) {
            addErrorMessage("Suma de votos depositados calculados menor que cero");
            return "fail";
        }

        // Validar que el detalle de votos no sea mayor al rango de votos por JRV
        if (voteFsln > limitVotes) {
            addErrorMessage("Cantidad de votos invalida para FSLN");
            return "fail";
        }
        if (votePlc > limitVotes) {
            addErrorMessage("Cantidad de votos invalida para PLC");
            return "fail";
        }
        if (voteAln > limitVotes) {
            addErrorMessage("Cantidad de votos invalida para ALN");
            return "fail";
        }
        if (votePrn > limitVotes) {
            addErrorMessage("Cantidad de votos invalida para APRE");
            return "fail";
        }
        if (voteAc > limitVotes) {
            addErrorMessage("Cantidad de votos invalida para APLI");
            return "fail";
        }

        return "success";
    }

    public String search() {
        if (jrv != null) {
            document = getElection().getDocument(jrv, counting, round);

            jrv = getElection().getJrv(jrv.getId());
            town = jrv.getBallotCentre().getTown();
            ballots = getElection().findBallotCentres(town);
            ballotCentre = jrv.getBallotCentre();

            if (document != null) {
                this.votes = document.getVotes();

                if (this.votes != null) {
                    for (Vote vote : votes) {
                        if (vote.getParty().getInititals().equals("PLC")) {
                            votePlc = vote.getAmount();
                        } else if (vote.getParty().getInititals().equals("FSLN")) {
                            voteFsln = vote.getAmount();
                        } else if (vote.getParty().getInititals().equals("ALN")) {
                            voteAln = vote.getAmount();
                        } else if (vote.getParty().getInititals().equals("APRE")) {
                            votePrn = vote.getAmount();
                        } else if (vote.getParty().getInititals().equals("APLI")) {
                            voteAc = vote.getAmount();
                        }
                    }
                }
            } else {
                document = new Document();
            }
        }

        return "success";
    }

    public String modify() {
        System.out.println("This is the modification procedure");
        if (validations().equals("fail")) {
            return "fail";
        }

        // Modify votes for every Party
        votes = document.getVotes();

        for (Vote vote : votes) {
            if (vote.getParty().getInititals().equals("PLC")) {
                vote.setAmount(votePlc);
            }
            if (vote.getParty().getInititals().equals("FSLN")) {
                vote.setAmount(voteFsln);
            }
            if (vote.getParty().getInititals().equals("ALN")) {
                vote.setAmount(voteAln);
            }
            if (vote.getParty().getInititals().equals("APRE")) {
                vote.setAmount(votePrn);
            }
            if (vote.getParty().getInititals().equals("APLI")) {
                vote.setAmount(voteAc);
            }
            getElection().storeVote(vote);
        }

        document.setElectionType(electionType);
        document.setCounting(getCounting());
        document.setRound(getRound());
        document.setJrv(jrv);
        document.setVotes(votes);

        // Audit
        Audit audit = document.getAudit();
        audit.setModifiedBy(getElection().getCurrentUser());
        audit.setModifiedDate(new Date());

        document.setAudit(audit);
        calculations();

        try {
            getElection().storeDocument(document);
        } catch (HibernateOptimisticLockingFailureException e) {
            clear(document);
            e.getMessage();
            return "fail";
        } catch (BusinessException e) {
            clear(document);
            addErrorMessage("Request was rejected, " + e.getMessage());
            return "fail";
        }

        addErrorMessage("Exito");
        System.out.println("Finished save process");
        reset();
        return "success";
    }
}